iT邦幫忙

2026 iThome 鐵人賽

DAY 30
0

📝 本系列為 iThome 鐵人賽學習筆記,屬個人教學與非商業用途;文中法規與標準內容均以自身理解後的話轉述並註明出處,非逐字引用。

階段四|怎麼落地:從技術棧示範

從一條法規縫隙,到一份可執行的白皮書

三十天,走到終點

三十天前,這個系列從一個很具體的困境開始(Day 1):人工智慧基本法通過了,但真正規範「你該怎麼做」的各部會作用法還沒到位——開發者卡在一條「法律有了、細則未明」的縫隙裡,不知道手上的 AI 專案到底該符合什麼、又該怎麼證明自己合規。

整個系列要回答的,就是這個困境。而回答的方式,濃縮成一句話,就是本系列的標題——「從法條到程式碼」:把最上層那些抽象的法規與標準,一層一層往下翻譯,最後變成一行行跑得起來的程式、一份份拿得出手的證據。

今天是最後一天。我們要做三件事:回望這條貫穿三十天的路、把成果合成一份可再利用的白皮書、並留下一個持續追蹤的觀察點。

回望:四個階段,一條貫穿的路

這三十天,沿著「從法條到程式碼」的方向,走過了如下圖所示的四個階段:

四階段的貫穿路徑

  • 第一階段|威脅與風險(Day 1–5):先立攻防的技術味。從法規縫隙講起,看大型語言模型(Large Language Model,以下簡稱 LLM)的資安為何與傳統資安不同,用開放全球應用程式安全計畫(Open Worldwide Application Security Project,以下簡稱 OWASP)的十大風險盤點威脅,並親手把一個沒設防的 AI 客服打穿——先讓讀者「痛」,才知道後面的制度與技術在防什麼。
  • 第二階段|制度與標準(Day 6–14):把骨架立起來。深入人工智慧基本法的七大原則,逐條深挖 ISO/IEC 42001(人工智慧管理系統標準)與台灣的 CNS 42001,並對照歐盟人工智慧法(European Union Artificial Intelligence Act,EU AI Act)與美國國家標準暨技術研究院(National Institute of Standards and Technology,NIST)的框架——讓讀者知道「國際上是怎麼管的、台灣接軌到哪」。
  • 第三階段|機構與資源(Day 15–20):認識台灣本土的治理生態。從制度地圖,到 AI 產品與系統評測中心(Artificial Intelligence Evaluation Center,以下簡稱 AIEC)、測試實驗室與驗證機構,再到十大評測項目與採購自評的語言——讓讀者知道「在台灣,找誰、用什麼標準驗」。
  • 第四階段|技術落地(Day 21–30):把前面全部翻譯成程式碼。用一套醫院檢索增強生成(Retrieval-Augmented Generation,以下簡稱 RAG)客服當靶子,逐層蓋上資料、輸入、輸出、存取、稽核五層防禦,用紅隊測試驗證、做供應鏈治理,最後收斂成一份可執行的檢核表。

四個階段,正好是一條完整的翻譯鏈:威脅(為什麼要管)→ 制度(該遵循什麼)→ 機構(找誰驗)→ 技術(怎麼做、怎麼證明)。 這條鏈,就是「從法條到程式碼」的全貌。

一以貫之的五條紀律

如果要把三十天濃縮成幾條最重要的原則——那些不管做哪一層、都反覆出現的「紀律」——會是如下圖所示的五條:

貫穿全系列的五條紀律

  1. 把安全建在機制上,而不是模型的善意上。從 Day 4 的提示注入,到 Day 25 的存取控制,反覆證明同一件事:模型的「自律」可以被話術繞過,真正的防線要建在模型之外——用檢索層過濾、用確定性的檢查,而不是拜託模型「請你乖一點」。
  2. 縱深防禦,沒有單一萬靈丹。資料、輸入、輸出、存取、稽核——每一層都會有守不住的時候,安全來自多層獨立防線的疊加。任何一層我們都誠實地標出它的極限。
  3. 留下證據,把「有做」變成「能證明」。每一天的防禦,最後都落成一份可驗證的東西:紅隊報告、稽核日誌、AI 物料清單。合規不是「我覺得安全」,而是「我拿得出證據」。
  4. 驗證,而不是假設。蓋好防禦不等於守得住(Day 26);釘選了元件不等於它安全(Day 28)。每一個「應該沒問題」,都要用實跑、用紅隊、用比對去換成一個確定的答案。
  5. 這是持續運轉的循環,不是一次性的專案。法規會修、標準會改版、威脅會演化——治理是一個要不斷「規劃、執行、查核、行動」的循環,不是勾完一次就結案。

這五條,比任何單一技術都重要——因為技術會過時,但這些紀律不會。

白皮書合成:把三十天收攏成一份資產

最後一個技術動作,是把這三十天散落的成果,合成一份可交付、可再利用的白皮書(完整檔在 程式碼/Day30/build_whitepaper.py)。

這支合成器有一條刻意的設計原則,值得先講:白皮書裡沒有任何一個數字、任何一格內容是手寫的。 全部從專案的實際狀態讀出來。理由很現實——手寫的摘要一定會過期。今天抄一份檢核表進去,明天改了檢核表,白皮書就悄悄變成錯的,而且沒有人會發現。所以合成器寧可去讀原始檔案,也不自己存一份副本。

目錄:掃描三十篇的標題

先是匯入與兩個常數——ROOT 指向專案根目錄,STAGES 則是四階段的分界:

import glob
import os
import re

# 專案根目錄(本檔在 程式碼/Day30/,往上三層即根)
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
HERE = os.path.dirname(os.path.abspath(__file__))

# 四階段的分界(起日、迄日、名稱)
STAGES = [
    (1, 5, "第一階段|威脅與風險"),
    (6, 14, "第二階段|制度與標準"),
    (15, 20, "第三階段|機構與資源"),
    (21, 30, "第四階段|技術落地"),
]

接著是核心邏輯,很單純:讀每一篇 DayNN.md 的第一行標題,依 STAGES 的分界歸類:

def read_title(day: int) -> str:
    """從 DayNN.md 第一行 '# Day NN:標題' 抽出標題。"""
    path = os.path.join(ROOT, f"Day{day:02d}.md")
    if not os.path.exists(path):
        return "(未完成)"
    first = open(path, encoding="utf-8").readline().strip()
    m = re.match(r"#\s*Day\s*\d+[::]\s*(.+)", first)
    return m.group(1) if m else "(無標題)"

read_title() 用一行正規表示式(Regular Expression,一種文字比對規則,見 Day 22),把每篇文章第一行的標題抽出來。這也呼應了一個小道理——因為一路遵守「檔案從 # Day NN:標題 開始」的規範,收尾時才能這樣自動化地把它們收攏起來。 一致的紀律,讓後續的自動化成為可能。

核心:直接嵌入 Day 29 的自評表

白皮書的第二節是它真正的價值所在——那份《AI 系統資安自評表》。合成器不重打,而是直接去讀 Day 29 那支查核工具的產出:

def read_self_assessment() -> str:
    """讀入 Day 29 產出的自評表;沒有就提示先去跑那支程式。"""
    path = os.path.join(ROOT, "程式碼", "Day29", "自評表.md")
    if not os.path.exists(path):
        return "> ⚠️ 尚未產出自評表,請先執行 `程式碼/Day29/compliance_checklist.py`。"
    body = open(path, encoding="utf-8").read()
    # 去掉自評表自己的大標,只留說明與表格,避免白皮書出現兩層標題
    kept = [ln for ln in body.splitlines() if not ln.startswith("# ")]
    return "\n".join(kept).strip()

這幾行看起來平淡,但它讓整條鏈接了起來:改一次 assessment.json → 重跑 Day 29 → 重跑這支合成器 → 白皮書自動更新。 白皮書從此不是一份靜態文件,而是專案狀態的一個投影。

資產清點:用數的,不用宣稱的

第三節是可再利用資產。這裡同樣不寫死數量,而是實際去數:

def count_assets() -> dict:
    """實際清點可再利用的資產數量,而不是宣稱。"""
    return {
        "程式": len(glob.glob(os.path.join(ROOT, "程式碼", "Day*", "*.py"))),
        "配圖": len(glob.glob(os.path.join(ROOT, "圖檔", "Day*", "*.png"))),
        "知識庫": len(glob.glob(os.path.join(ROOT, "程式碼", "Day*", "knowledge*", "*.md"))),
    }

這呼應了 Day 29 那條規則——不相信宣稱,只相信檔案。 白皮書說有十七支程式,是因為真的數到十七個 .py 檔。

追蹤清單:這份文件何時該回頭修

第四節是這次新增、也是最實用的一節。與其在結尾寫一句「請定期更新」,不如直接寫成一張表:追什麼、去哪裡看、什麼時候該回頭、要改白皮書的哪一格。

# 追蹤清單:這份白皮書會因為什麼而過期,該去哪裡看
WATCHLIST = [
    ("各部會 AI 作用法與指引", "國家科學及技術委員會、各目的事業主管機關",
     "新指引發布時", "檢核表的「制度來源」欄"),
    ("資安法規與採購要求", "數位發展部資通安全署、行政院公共工程委員會",
     "法規修正時", "Day 20 的責任等級與通報義務"),
    # …… 其餘三項即下文「後續追蹤」一節那張表的後三列 ……
]

把它寫進程式而不是寫在文章結尾,是為了讓它跟著白皮書一起被產出、一起被看見。

把四節組起來:主程式

最後由 build() 把四節依序串成一份 Markdown,__main__ 負責寫檔並印出摘要:

def build() -> str:
    """合成白皮書 Markdown,回傳字串。"""
    lines = [
        "# 《AI 治理與資安合規實戰指南》白皮書",
        "",
        "> 由 iThome 鐵人賽 30 天系列合成。把上層法規標準,一路翻譯到可執行的技術控制與程式碼。",
        "> 本文件由 `程式碼/Day30/build_whitepaper.py` 自動產生,內容隨專案實際狀態更新。",
        "",
        "## 一、目錄:從法條到程式碼的四階段",
        "",
    ]
    for start, end, name in STAGES:
        lines.append(f"### {name}(Day {start}–{end})")
        for day in range(start, end + 1):
            lines.append(f"- Day {day:02d}:{read_title(day)}")
        lines.append("")

    lines += ["## 二、核心交付物:AI 系統資安自評表", "",
              "以下直接引用 Day 29 查核工具的產出,每一格佐證都經過存在性驗證。", "",
              read_self_assessment(), ""]

    assets = count_assets()
    lines += ["## 三、可再利用資產", "",
              f"- 可執行程式 {assets['程式']} 支:RAG 五層防禦、紅隊框架、"
              f"稽核日誌、供應鏈驗證、合規查核工具(`程式碼/DayNN/`)",
              f"- 概念與流程配圖 {assets['配圖']} 張(`圖檔/DayNN/`)",
              f"- 教學用知識庫文件 {assets['知識庫']} 份(`程式碼/DayNN/knowledge*/`)",
              "- 適用場景:醫院 AI 客服案、政府 AI 標案的自評、送測與稽核。", ""]

    lines += ["## 四、追蹤清單:這份文件何時該回頭修", "",
              "| 追什麼 | 去哪裡看 | 什麼時候回頭 | 要改白皮書哪裡 |",
              "| --- | --- | --- | --- |"]
    for what, where, when, fix in WATCHLIST:
        lines.append(f"| {what} | {where} | {when} | {fix} |")
    lines.append("")
    return "\n".join(lines)


if __name__ == "__main__":
    whitepaper = build()
    out = os.path.join(HERE, "白皮書.md")
    with open(out, "w", encoding="utf-8") as f:
        f.write(whitepaper)

    done = sum(1 for d in range(1, 31) if read_title(d) not in ("(未完成)", "(無標題)"))
    assets = count_assets()
    print(f"✅ 已合成白皮書 → {os.path.basename(out)}({len(whitepaper)} 字元)")
    print(f"   收錄文章:{done}/30 篇")
    embedded = os.path.exists(os.path.join(ROOT, "程式碼", "Day29", "自評表.md"))
    print(f"   嵌入 Day 29 自評表:{'是' if embedded else '否(請先跑 Day 29)'}")
    print(f"   清點資產:程式 {assets['程式']} 支、配圖 {assets['配圖']} 張、"
          f"知識庫 {assets['知識庫']} 份")
    print(f"   追蹤清單:{len(WATCHLIST)} 項")
    print("\n── 白皮書目錄預覽 ──")
    for start, end, name in STAGES:
        print(f"  {name}(Day {start}–{end})")

build() 這幾十行,正是前面那句「沒有任何數字是手寫的」的證明:目錄來自 read_title()、自評表來自 read_self_assessment()、資產數量來自 count_assets()——每一格都是讀出來的,沒有一格是打上去的。

實跑:一份白皮書就這樣長出來

把工具跑起來(python build_whitepaper.py),終端輸出如下:

✅ 已合成白皮書 → 白皮書.md(3095 字元)
   收錄文章:30/30 篇
   嵌入 Day 29 自評表:是
   清點資產:程式 21 支、配圖 167 張、知識庫 9 份
   追蹤清單:5 項

── 白皮書目錄預覽 ──
  第一階段|威脅與風險(Day 1–5)
  第二階段|制度與標準(Day 6–14)
  第三階段|機構與資源(Day 15–20)
  第四階段|技術落地(Day 21–30)

三十篇合成一份白皮書

(資產數量是執行當下數出來的,所以每次新增程式或配圖,重跑一次就會不一樣——這正是它的設計目的。)

一份完整的 白皮書.md 就生成了,四節俱全:依四階段編排的三十篇目錄、Day 29 那份每格佐證都經過查核的自評表、清點過的可再利用資產、以及一份追蹤清單。這份文件,就是整個系列真正的最終交付物:不是三十篇要人一篇篇讀的文章,而是一份能拿在手上、翻得動、用得上的白皮書。

這份資產,可以怎麼再利用?

這份白皮書與檢核表,不是鐵人賽結束就作廢的作業,它是一份能落到真實場景的資產。如下圖所示,它有兩個再利用場景:

白皮書的兩個再利用場景

  • 醫院 AI 案:本系列的 RAG 靶機,情境就是醫院客服。那套「資料治理→輸入輸出防禦→存取控制→稽核」的五層架構、加上檢核表,可以直接當成一家醫院導入 AI 客服時的資安設計藍圖與自評工具——尤其醫療個資敏感,這套防護與可追溯性正是剛需。
  • 政府 AI 標案:檢核表的骨架是 AIEC 十大評測項目,天生對接台灣的評測與驗證體系。它可以放進標案的規格書與驗收標準(回指 Day 20),把「廠商要證明 AI 安全合規」這件事,變成一份逐項、可稽核的要求——這就是把整套治理語言,變成採購與驗收的共同標準。

換句話說,三十天的成果不只是「學會了」,而是留下了一套可以重複使用的方法論與工具——換一個專案、換一個場景,把靶機換掉、把檢核表的落實狀態重填,這套流程就能再跑一遍。

後續追蹤:這是一個「活的」議題

最後,必須誠實地留下一個提醒:這份白皮書,不是一份「完成」的文件,而是一份「活的」文件。

本系列反覆強調過,台灣的 AI 治理正在滾動式地成形:人工智慧基本法雖已通過,但各部會的作用法、細則、指引仍在陸續發布;AIEC 的評測項目、ISO/CNS 標準也都可能改版;而攻擊手法更是天天在演化。

問題是,「要定期更新」這句話講起來容易,執行起來卻沒有著力點——更新什麼?去哪裡看?改哪裡?所以合成器把它寫成了一張具體的追蹤清單,隨白皮書一起產出:

追什麼 去哪裡看 什麼時候回頭 要改白皮書哪裡
各部會 AI 作用法與指引 國家科學及技術委員會、各目的事業主管機關 新指引發布時 檢核表的「制度來源」欄
資安法規與採購要求 數位發展部資通安全署、行政院公共工程委員會 法規修正時 Day 20 的責任等級與通報義務
AIEC 評測項目 數位產業署 AI 產品與系統評測中心 評測項目調整時 檢核表的十列骨架
ISO/IEC 42001 與 CNS 42001 ISO、經濟部標準檢驗局 標準改版時 檢核表的「42001 落點」欄
新型攻擊手法 OWASP LLM Top 10、資安社群 出現新手法時 Day 26 的紅隊案例庫

這張表的用法很單純:每一列都是一組「訊號 → 動作」。 看到訊號(例如衛福部發布了醫療 AI 指引),就知道要動白皮書的哪一格(檢核表的制度來源欄),而不必重讀三十篇文章去想哪裡受影響。這比一句「請保持關注」有用得多。

至於複查頻率,實務上的建議是:跟著專案的節奏走——每次要投標、送測或做內部稽核之前,把這張表過一遍;沒有這些觸發事件時,至少每半年一次。

「邊做邊追」——追一個還在成形中的活議題——正是這個題目最長期的價值所在。三十天不是終點,而是替後續的持續追蹤,打下了一個有結構、有工具、有紀律的起點。

合成器不會替你思考

最後把這支工具的邊界說清楚:

  • 它組裝文件,不產生判斷。 合成器會忠實地把標題、自評表、資產數量拼起來,但「這份自評填得對不對」「這個對映合不合理」,它一概不知道。工具能保證的是一致性(白皮書不會跟專案現況脫節),不是正確性
  • 它反映的是這個 demo 的狀態,不是你的專案。 這份白皮書描述的是一套教學用的醫院 RAG 客服。真要用在實際案子上,檢核表的十列骨架與追蹤清單可以照搬,但自評狀態與佐證路徑必須整份換掉——否則就是拿別人的成績單去投標。
  • 追蹤清單本身也會過期。 表裡的機關名稱、來源網站都可能改組或搬遷(本系列撰稿查證時就遇到法規已修正更名的例子,見 Day 20)。這張表要跟著維護,它不是一勞永逸的訂閱清單。

換句話說,這支工具處理的是「不要讓文件跟現實脫節」這件事——這已經是很多合規文件做不到的了,但它終究只是把人的判斷保存下來,不能取代那個判斷。

結語:從一條縫隙,到一份藍圖

三十天前,我們站在一條「法律有了、細則未明」的縫隙前,感到無所適從。三十天後,這條縫隙沒有完全消失——它本來就需要時間,靠整個生態一起把它補起來——但我們手上,已經多了一份東西:一張把抽象法規一路翻譯到具體程式碼的地圖,和一套能拿去用、能持續更新的工具。

從 Day 1 的一條法規縫隙,到 Day 30 的一份可執行白皮書,這趟「從法條到程式碼」的旅程,到這裡告一段落。法規會繼續更新、技術會繼續演化,但這套「把上層要求翻譯成下層控制、再用證據證明它」的方法,會一直有用。

感謝每一位讀到這裡的讀者。願這份白皮書,能成為你手上那個 AI 專案,真正用得上的起點。


  • 程式碼:程式碼/Day30/build_whitepaper.py(白皮書合成器)與其產出 程式碼/Day30/白皮書.md。程式掃描本系列 30 篇文章標題、依四階段整理,並嵌入 Day 29 核心檢核表,結果為真實執行輸出。
  • 參考出處:本篇為系列總結,內容回顧 Day 1–29;所涉《人工智慧基本法》、ISO/IEC 42001/CNS 42001、AIEC 十大評測項目等,各自出處見對應日次;四階段架構與「從法條到程式碼」方法論為本系列原創整理。

上一篇
Day 29:AI 專案資安合規檢核表(白皮書核心)
系列文
從法條到程式碼:台灣 AI 治理與資安合規實戰指南30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Chill 77
iT邦新手 3 級 ‧ 2026-09-17 09:07:55

恭喜完賽! 期待明年! /images/emoticon/emoticon61.gif

我要留言

立即登入留言